        -=( 7A69#11 )=--=( art2 )=--=( Programacion )=--=( Ripe )=-

               Linux Programing; de todo un poco
               ---------------------------------

0. Indide
----------

		1. Introduccion
		2. Tipos de lenguajes
			2.1. Scripts, interpretando el codigo
			2.2. Lenguajes compilados
		3. Las llamadas al sistema
		4. Adentrandonos en la programacion
			4.1. Pseudocodigo; hablando nuestro idioma
			4.2. Programando el Hola mundo!!
			4.3. Compilando C
			4.4. Programacion modular; divide y venceras
				4.4.1. Introduccion
				4.4.2. Las ventajas dividir
				4.4.3. Como hacerlo?
		5. Conclusion



1. Introduccion.
---------------- 

Existe en el mercado una numerosa gama se sistemas operativos, cada uno con
sus ventajas y desventajas, y cada uno con sus propias herramientas a la hora 
de programar. Lo que en esta primera entrega del UNIX Programing vamos a 
comentar va a ser el como funciona un sistema operativo UNIX, y en que nos va a
influir a la hora de programar, ademas veremos las herramientas basicas con las
que un programador cuenta. Debido a que Linux es un sistema operativo gratuito,
y que actualmente esta al alcance de todo el mundo me voy a centrar en el a la 
hora de llevar esta serie de articulos, sinembargo muchas de las cosas que aqui
cuente seran aplicables a la gran mayoria de los sistemas UNIX. Si no dispones 
de Linux en tu sistema, y no sabes donde conseguirlo date una vuelta por 
http://www.linuxiso.org o pregunta en el canal #linux de cualquier red de IRC.

Podriamos decir, a grandes rasgos, que existen dos tipos de programacion, 
la de scripts interpretados y la de programas compilados. La mayor diferencia
entre estos dos tipos persiste a la hora de ejecutar el programa. Cuando 
ejecutamos un script, el codigo maquina que el computador puede entender se
genera en tiempo de ejecucion, lo que quiere decir menor rendimiento y mas
recursos, mientras que si hablamos de un lenguaje compilado, y debido a que el 
fichero se encuentra ya en codigo maquina (Aunque no en texto totalmente llano,
ya que debemos tener en cuenta las cabeceras con la que lso ficheros 
ejecutables se prestan, como podria ser la cabecera de un ELF), la ejecucion es
mucho mas rapida y agotando una menor cantidad de recursos. Pero no todo esta 
en contra de los scripts y a favor de los lenguajes compilados, al contrario, 
hay bueno y malo para todos, sobretodo teniendo en cuenta que programar un 
script suele ser mucho mas rapido, ya que no requiere compilacion tras cada 
modificacion, lo que hace que el programador pueda realizar sus pruebas mucho 
mas rapido. En el mundo de la programacion con lenguajes compilados se ha 
tratado de imponer una solucion a este problema, y la solucion es, podriamos 
decir, mas que aceptable, se trata de la programacion modular, o la division 
de un programa en modulos, como prefirais llamarlo. Vista esta 
introduccion/explicacion vamos a profundizar un poco mas en ello.


		       -= 2. Tipos de lenguajes =-
			  ----------------------

2.1. Scripts, interpretando el codigo.
--------------------------------------

Cabe decir que los lenguajes interpretados son una cosa relativamente 
nueva, y que mucho antes que estos aparecieran los lenguajes de programacion 
que requieren compilacion ya habiean aparecido, esto es realmente logico, ya 
que los interpretes (programas que se encargan de convertir el codigo del 
script a un codigo legible por la maquina en tiempo de ejecucion) estan 
programados en lenguajes compilados, pero este no es el tema a tratar.

Asi pues un interprete trabaja de la siguiente manera. Lee una instruccion 
de un fichero fuente y ejecuta un pedazo de codigo maquina asociado a dicha 
instruccion, y repite este proceso una y otra vez hasta que el programa 
termina. Esto quiere decir que para que un mismo script pueda ejecutarse en 
diferente maquinas estas deben tener un interprete de dicho script adaptados a 
la misma.

Ejemplos de interpretes pueden ser Perl, Bash y Awk entre otros muchos. 
Para mas informacion utiliza los manuales del sistema.


    -= 2.2. Lenguajes compilados =-
       -------------------------

	Los lenguajes compilados, como su nombre bien indica, necesitan de un 
compilador para trabajar. El compilador se encarga de generar el codigo maquina
apartir de un fichero fuente, pero el proceso no es tan simple como parece. 
Antes que nada el compilador genera un fichero objeto, que contendra una 
secuencia de codigo maquina pero que aun no sera ejecutable, ya que necesita 
ser lincado, de ello se encargara el linker (en muchas ocasiones, por no decir 
en casi todas, se habla del compilador y el linker como de una misma cosa), que
se encarga de enlazar librerias. Es gracias a el, ademas, que se nos permite la
programacion modular, ya que este puede tratar con varios ficheros objetos para
generar un codigo ejecutable. Otra cosa, realmente util que un linker nos 
permite es la de usar el codigo de determinadas librerias, ya sean estaticas o 
dinamicas. Hablaremos de una libreria estatica cuando esta se aade al programa
como si de un modulo mas se tratara, y hablamos de librerias dinamicas cuando 
esta se encuentra en un fichero aparte. La ventaja de tener las librerias en 
un fichero aparte es que los ficheros ejecutables son considerablemente mas 
pequeos, y que ademas, podemos mejorar algunas de las funciones de la libreria 
sin tocar para nada el fichero ejecutable, siempre teniendo en cuenta que no 
debemos cambiar la forma de trabajas la entrada y salida de sus funciones.

Ejemplos de compiladores pueden ser Gcc, j++.... y un linker puede ser ld. 
Para mas informacion utiliza los manuales del sistema. 


     -= 3. Las llamadas al sistema =-
        ---------------------------

Para realizar cuanquier accion, en un sistema operativo monolitico, como 
puede ser linux, esta debe ser realizada por el kernel, pero nuestros programas
no tienen acceso al mismo. Para ello se inventaron las Syscalls, tambien 
conocidas como llamadas al sistema o APIs. La importancia de las syscalls en el
mundo de la programacion en Linux es mucha, ya que sin ellas seria imposible 
trabajar. Las llamadas al sistema se dividen en 6 grupos basicos; 
Administracion de ficheros, Administracion de directorios y sistemas de 
archivos, Proteccion y permisos, Administracion procesos, Seales y Gestion del
tiempo. Cada uno de estos grupos consta de varias llamadas al sistema.

Para indicarle al kernel que queremos usar una syscall usaremos la 
interrupcion 0x80, de manera que en el registro EAX tendremos el valor 
correspondiente a la syscall y en EBX, ECX.... tendremos los parametros para 
dicha llamada al sistema. Si el numero de llamadas parametros que solicita la 
syscall sobrepasa el numero de registros que podemos usar deberemos crear un 
vector con los parametros y pasar la posicion de memoria en EBX.

	Veampos un ejemplo de syscall:

open("/etc/passwd", O_RDONLY);		/* Como veis no es dificil de  */
    				        /* entender.                   */

En este caso usamos la syscall open(), que forma parte del grupo de 
Administracion de ficheros, en ASM seria una cosa similar a esta:

mov %eax,0x05       ; 0x05 es el valor de la syscall open(), si quieres
                    ; saber el valor de cada una de las syscalls mira  
                    ; el fichero /usr/include/asm/unistd.h

mov %ebx,0x00bf34aa ; 0x00bf34aa es la posicion de memoria que contiene
                    ; la cadena "/etc/passwd\0". El 0 del final es 
                    ; importante, pues le dice a la syscall hasta donde 
                    ; debe leer para interpretar el nombre del fichero.

mov %ecx,0x00	    ; Es el valor de O_RDONLY, definido en bits/fcntl.h
int 0x80	    ; Llamamos a la interrupcion 0x80, ahora le toca 
                    ; jugar al kernel.
        
Todas las syscalls, tras terminar, devuelven un valor, que se suele usar 
para indicar si esta ha terminado con exito o se ha producido algun tipo de 
error. Este valor queda almacenado en EAX.

Si no has entendido esta ultima parte no te preocuper demasiado, ya que no 
te sera necesario a no ser que quieras programar a bajo nivel, en ASM.


   -= 4. Adentrandonos en la programacion =-
      -----------------------------------

4.1. Pseudocodigo; Hablando nuestra lengua.
-------------------------------------------

Bien, todos habreis visto alguna vez el codigo fuente de alguna aplicacion,
sea en el lenguaje que sea, y os habreis dado cuenta que, en la mayora de los 
casos la funciones o intrucciones tienen nombre ingleses, lo que puede suponer 
una dificultad para el programador que no conozca dicho idioma, pero este no es
el tema a tratar, asi que vayamos mas al grano.

Cuando hablamos de pseudocodigo hablamos de un codigo posterior a las 
fuentes del programa que es totalmente comprensible por el hombre (por lo que, 
en principio, al computador le suena a chino). Los instructores en programacion
recomiendan siempre realizar una planificacion con organigramas y pseudocodigos
antes de realizar un programa, sinembargo, cuando se trata de programas 
pequeos, pocos programadores lo hacen. Una caracteristica del pseudocodigo es 
que es igual sea cual sea el lenguaje de programacion que tengamos intencion de
usar. Veamos un ejemplo de un programa que realiza una suma de dos numeros.

--/ suma.pse /--

inicio ejecucion
leo valor1
leo valor2
sumo valor1 y valor2, almaceno el resultado en valor3
imprimo valor3
finalizo ejecucion

--/ suma.pse /--

Como podeis ver no hay que conocer ningun lenguaje de programacion para 
entender lo que dicho "programa" realiza.

Todo buen lenguaje de alto nivel que se precie debe disponer de expresiones 
que sirvan para la realizacion de saltos condicionales y repeticion de 
instrucciones. Como es obio al tratar con el pseudocodigo tambien disponemos de
este tipo de expresiones (realmente en el pseudocodigo podemos realizar 
cualquier cosa que se pueda expresar en palabras). Seguidamente mostrare unos 
ejemplos que creo que no necesitan demasiada expliacion.

--/ mayor.pse /--

inicio ejecucion
leo valor1
leo valor2
si valor1 es igual que valor2 
  imprimo "son iguales" por pantalla 
  y finalizo ejecucion
de lo contrario
   si valor1 es mayor que valor2
     imprimo "el mayor es valo1" por pantalla
     y finalizo ejecucion
   de lo contrario
     imprimo "el mayor es valor2"
     y finalizo ejecucion

--/ mayor.pse /--

Podemos ver el uso de "si esto haz esto de lo contrario haz esto", no tiene
ningun secreto.

--/ conta10.pse /--

inicio ejecucucion
asigno 0 a valor1
mientras valor1 es menor que 10
  sumo 1 a valor1
  imprimo valor1
finalizo ejecucion

--/ conta10.pse /--

Podemos ver el uso de "mientras esto haz esto", tampoco tiene mas secretos.

No vamos a profundizar mas en el pseudocodigo, pues considero que la idea 
basica se ha entendido a la perfeccion, y tampoco es que haya mucho mas que 
contar.



	-= 4.2. Programando el Hola mundo! =-
	   -------------------------------

Todo aquel que haya leido algun libro o manual inciacion a algun lenguaje 
de programacion habra oido hablar del conocido "hola mundo!!". Si bien es un 
programa muy tonto ha ayudado a muchos a comprender que es la programacion, por
ello, en este curso de programacion en Linux no podiamos ser menos. La unica 
diferencia entre este curso y el resto reside en que nosotros no usamos ningun 
lenguaje de programacion concreto, por lo que escribiremos dicho programa en 
pseudocodigo para luego escribirlo en un par de lenguajes (Usaremos unicamente 
los lenguajes mas usados, pues si tubieramos que tratarlos todos no 
terminariamos nunca). Seguro que por tu mente ya corre la solucion del 
problema... como hacer en pseudocodigo un programa que imprima hola mundo!! en
pantalla? La pregunta nos da casi la respuesta:

--/ holamundo.pse /--

inicio ejecucion
imprimo "hola mundo!!" en pantalla
finalizo ejecucion

--/ holamundo.pse /--

	Simple no?

Pues veamos segudamente como seria en shellscript dicho programa (ten en 
cuenta que en todos los ejemplo de shellscript nos basaremos en bash, por ser, 
en la actualidad el interprete mas usado, siembargo la mayoria de las cosas se 
podran aplicar a los shells mas comunes como csh, ksh, etc).

--/ holamundo.sh /--

#!/bin/bash
echo Hola mundo!!
exit 0

--/ holamundo.sh /--

Como podemos ver, y esto es muy comun en el mundo de los interpretes en 
UNIX, la primera linea la usamos para indicar el interprete que vamos a usar, 
si omitimos esa linea, el sistema tomara como interprete el predeterminado, que
es el que estamos usando actualmente. No hay ninguna instruccion que indique 
inicio de ejecucion, por lo cual esta empieza al inicio del fichero. Vemos como
el programador, yo en este caso, se sirve de la instruccion echo para imprimir 
por pantalla Hola mundo!!, y acto seguido, con una llamada a exit (que podria 
omitirse ya que se encuentra al final del fichero) finaliza la ejecucion del 
programa.

Vamos a ver como seria la misma situacion en perl, otro lenguaje 
interpretado, muy usado para programar cosas rapidamente.

--/ holamundo.pl /--

#!/usr/bin/perl
print 'Hola mundo!!'
exit 0

--/ holamundo.pl /--

Como podeis ver la cosa no cambia demasiado. Seguimos usando la primera 
linea para indicar donde se encuentra el interprete que queremos usar, y 
seguimos usando exit para finalizar la ejecucion. El unico cambio que notamos 
es el de la intruccion que substituye el imprimira pantalla en el pseudocodigo,
pues en el shellscript hemos usado echo y aqui hemos usado print.

Finalmente, y como ultimo lenguaje a tratar vamos a observar como seria el 
programa equivalente en un lenguaje compilado como puede ser C.

--/ holamundo.c /--

int main() {
  printf("Hola mundo!!");
  exit(0);
}

--/ holamundo.c /--

Aqui la cosa cambia un poco. De entrada, y al no tratarse de un lenguaje 
interpretado podemos ver que la primera linea (que usabamos antes para indicar
que interprete queriamos usar) se omite. Otro cambio significativo es el uso de
la primera linea, ya que indica inidio de ejecucion, cosa que en los dos 
anteriores ejemplos no habiamos usado. Si no entiendes bien el ejemplo, te 
recomiendo que leas el curso de C que se publica perdiodicamente en este mismo 
e-zine.


    4.3. Compilando C
    -----------------

Dijimos anteriormente que para poder ejecutar un programa escrito en un 
lenguaje compilable, como puede ser el C, es necerario realizar dos procesos, 
el de compilacion y el de linkado con las librerias dinamicas o estaticas. Lo 
que ahora vamos a ver es como se realiza dicho proceso en C, el lenguaje mas 
usado a la hora de crear aplicacion en los sistemas UNIX.

El compilador que se suele usar en linux para compilar aplicaciones en C es
el GNU C Compiler (GCC) y para linkar se usa el GNU Linker (LD). Normalmente el
programador no toma contacto con el linkador ya que el mismo gcc se encarga de
llamar a ld ahorrando asi trabajo a la hora de compilar. De manera que si lo 
que queremos es crear el fichero objeto y no el fichero ejecutable (es decir, 
no queremos que entre en accion el linker) debemos especificarlo, veremos como.

Antes que nada veamos una compilacion sencilla, por ejemplo la del programa 
holamundo.c que vimos anteriormente.

-------------------------------------------------------------------------------
|                                                                             |
|	$ cat holamundo.c                                                     |
|	int main() {                                                          |
|  	  printf("Hola mundo!!");                                             |
|	  exit(0);                                                            |
|	}                                                                     |
|	$ gcc holamundo.c                                                     |
|	$ ./holamundo                                                         |
|	bash: ./holamundo: No existe el fichero o el directorio               |
|	$ _                                                                   |
|                                                                             |
-------------------------------------------------------------------------------

No se ha realizado correctamente la compilacion? La respuesta es si, el 
problema es que el nombre del ejecutable sera a.out a no ser que nosostros 
especifiquemos otro distinto con el modificador -o.

-------------------------------------------------------------------------------
|                                                                             |
|	$ ./a.out                                                             |
|	Hola mundo!!                                                          |
|	$  gcc holamundo.c -o holamundo                                       |
|	$ ./holamundo                                                         |
|	Hola mundo!!                                                          |
|	$ _                                                                   |
|                                                                             |
-------------------------------------------------------------------------------

Bien, crear un fichero ejecutable es realmente facil, pero veamos como se 
crearia fichero objeto.

-------------------------------------------------------------------------------
|                                                                             |
|	$ gcc holamundo.c -c                                                  |
|	$ ls holamundo.o                                                      |
|	holamundo.o                                                           |
|	$ _                                                                   |
|                                                                             |
-------------------------------------------------------------------------------

Como podemos ver, usamos el modificador -c para crear el fichero objeto, 
cuya extension es .o . Con el parametro -o podriamos, al igual que a la hora de
crear un fichero ejecutable especificar otro nombre de archivo.

Puede parecer que crear ficheros objeto no tiene ninguna utilidad, pero no 
es asi, ni mucho menos, lo veremos mas adelante, veremos que es util sobretodo 
a la hora de hacer programas modulares, aunque no sera el programa quien lo 
haga directamente, ya que se usara la herramienta "make". Ademas, es posible 
que tengamos intencion de distribuir un programa sin mostrar el codigo fuente, 
podemos entonces dejar que sea el fichero objeto el que llegue al usuario.



	-= 4.4. Programacion modular, divide y venceras =-
           --------------------------------------------

4.4.1. Introduccion
-------------------

Quien no ha visto nunca la tipica pelicula en la que aparece una 
persecucion? "tu por aqui y yo por alla" decian los malos. El lema es "divide y
venceras", y esto, aun que parezca extrao puede aplicarse al mudno de la 
programacion, el ejemplo mas claro de ello (y quiza el unico) es el de la 
programacion modular.


4.4.2. Las ventajas de dividir.
-------------------------------

Antes de introducirnos de lleno en el mundo de la programacion modular sera
bueno que expliquemos un poco las ventajas, que no son pocas, que aporta al 
programador el hecho de dividir un programa en modulos.

[*] - Reusando codigo: La posiblidad de reusar un modulo es una de las
      utilidades mas destacadas con la que nos encontramos. Gracias a ello
      podemos, por ejemplo, programar un modulo que contenga funciones para
      el envio de paquetes por red, y este podra ser usado por todos los
      programas que queramos siempre que insertemos el modulo.

[*] - Mayor comprension: Una division inteligente produce una mayor comprension
      de las fuentes del programa, ello conlleva tambien una gran ventaja, ya
      que permite que otros programadores entiendan mejor tu codigo ademas de
      facilitarte a ti la depuracion del mismo.

[*] - Compartir proyectos: A la hora de realizar programas grandes es realmente
      dificil que una persona sola pueda hacer todo el trabajo. Para
      solucionar esto, hay que sonsiderar la posiblidad de planificar una
      programacion modular, de manera que varios programadores puesan
      compartir un proyecto programando distintos modulos cada uno, que
      despues seran unidos.

[*] - Rapida recompilacion: Si habeis prestado atencion habreis leido que
      antes de disponer del fichero ejecutable disponemos de un fichero
      objeto. Pues para enlazar los modulos estos deben estar con sus
      respectivos ficheros objetos. Si nostros guardamos los ficheros
      objetos de cada modulo, y en el caso de que tengamos que cambiar algo
      en alguno de los modulos, solo temdremos que recompilar dicho modulo, lo
      que ahorra considerablemente tiempo al programador.



4.4.3. como hacerlo?
---------------------

Al contrario de lo que pueda parecer, hacer un programa en modulos no 
conlleva ningun tipo de complicacion, aunque se tiene que tener bien claro lo
que se quiere hacer, para ello, es recomendable hacer antes un esquema de la
filosofia a seguir, ya sea en mente (no muy recomendado) o en papel. Si
varios programadores van a compartir un proyecto deben pactar antes como
funcionaran las funciones de cada uno de los modulos en cuanto a entrada y
salida de la misma se refiere, de manera que el programador de un modulo pueda
usar la funcion de otro modulo sin saber realmente como esta programada.

Para ver como funciona la programacion modular lo mejor es tratarlo con un
ejemplo, y eso es lo que vamos a hacer. El ejemplo que he preparado es
realmente simple, un programa usara las funciones de un modulo para mostrar
errores, el programa es muy inutil, espero que no me mateis por ello.

Todo modulo debe componerse de dos ficheros, uno con extension .h que
usarmos para declarar tipos y funciones y uno con extension .c en el que se
encontraran los codigos fuentes de dichas funciones, veamos como seria el
modulo usado para mostrar mensages de error:

--/ mod_error.h /--

#ifndef MOD_ERROR

int gen_error(ERROR er);
int mor_error(ERROR er);

#endif

typedef *struct {
	int code;
	int fdout;
	char *text;
} ERROR;

--/ mod_error.h /--

Lo de MOD_ERROR lo explicare mas adelante.

--/ mod_error.c /--

#include <stdio.h>
#include <stdarg.h>
#define MOD_ERROR
#include "mod_error.h"

int fdprintf(int fd, char *formato, ...) {
  char buffer[MAXBUF];
  int bytes;
  va_list lista;
  va_start(lista, formato);
  vsprintf(buffer, formato, lista);
  va_end(lista);
  bytes=strlen(buffer);
  bytes=write(fd, buffer, bytes);
  return(bytes);
}

int gen_error(ERROR er) {
  if (ERROR==NULL) return(-1);
  fdprintf(er->fdout, "ERROR: %i : %s\n", er->code, er->text);
  exit(-code);
}

int mor_error(ERROR er) {
  if (ERROR==NULL) return(-1);
  fdprintf(er->fdout, "ERROR en la ejecucion\n");
  fdprintf(er->fdout, "CODIGO: %i\n", er->code);
  fdprintf(er->fdout, "MOTIVO: %s\n", er->texto);
  exit(-code);
}

--/ mod_error.c /--

Momento de explicar el porque usamos el #define MOD_ERROR. Nosotros en 
main.c haremos una inclusion del fichero mod_error.h, lo que quiere decir que 
las funciones quedaran declaradas dos veces, una en main.c y la otra en
mod_error.c produciendo asi un error de compilacion, para solucionar esto
definimos MOD_ERROR en mod_error.c y  hamos, mediante las directivas #ifndef y 
#endif que no se declaren las funciones.

Una cosa que cabe destacar es que fdprintf() no ha sido declarada en
mod_error.h, ello es asi ya que no pretendemos que el usuario la use como
parte del modulo, ya que es una funcion interna usada por las funciones de
error de mod_error.c.

Ahora veamos un ejemplo de uso de dicho modulo, el ejemplo mas tonto que
podais llegar a imaginar.

--/ main.c /--

#include <stdio.h>
#include "mod_error.h"

int main() {
  ERROR error;
  mensaje="No es posible realizar la suma";
  printf("Vamos a generar un error detallado con codigo 32, y cuyo\n
          motivo sera.... que no se puede realizar una suma\n");
  printf("-\n");
  error->code=32;
  error->fdout=2; /* hacemos que salga por stderr */
  error->motivo=mensaje;
  if (mor_error(error)==1) {
    /* error al producir el error */
    printf("jeje\n");
  }
  exit(0);
}
 
--/ main.c /-- 

Compilar un programa por modulos no es, ni mucho menos complicado. Tenemos
dos formas de hacerlo, manualmente o usando la erramienta "make" de la que
hable anteriormente. Ahora veremos con mas detalle todo esto. Empezaremos
compilandolo de forma manual.

Para compilarlo de forma manual tendremos que generar el fichero objeto de
el modulo y de main, para ello usaremos gcc con el modificador -c.

-------------------------------------------------------------------------------
|                                                                             |
|	$ gcc -c main.c                                                       |
|	$ gcc -c mod_error.c                                                  |
|	$ ls *.o                                                              |
|	main.o   mod_error.o                                                  |
|	$ _                                                                   |
|                                                                             |
-------------------------------------------------------------------------------

Seguidamente, y usando gcc tambien haremos el enlace (recuerda que gcc
llama a ld para realizar dicha tarea).

-------------------------------------------------------------------------------
|                                                                             |
|	$ gcc -o miprog main.o mod_error.o                                    |
|	$ ./miprog                                                            |
|	Vamos a generar un error detallado con codigo 32 y cuyo               |
|	motivo sera.... Que no se puede realizar una suma                     |
|	-                                                                     |
|	ERROR en la ejecucion                                                 |
|	CODIGO: 32                                                            |
|	MOTIVO: No es posible realizar la suma                                |
|	$ _                                                                   |
|                                                                             |
-------------------------------------------------------------------------------

Este metodo puede hacerse realmente pesado y repetitivo si tenemos una
gran cantidad de modulos (como suele ser). Para solucionar esa pesadez UNIX
pone a nuestra disposicion la erramienta "make", este programa trabaja 
basandose en una resglas establecidas por nostros en un fichero llamado 
Makefile y se encarga de gestionar de forma correcta los modulos de un 
programa.

Crear el Makefile es relativamente facil. Este fichero cuenta con varias
entradas que siguen la siguiente estructura.

	[fichero a crear]:[ficheros necesarios]
	[Acciones a realizar]

De manera que para generar el Makefile para nuestro programa debemos 
saber de que depende cada fichero, por lo que creamos una estructura como esta
que sigue:

	main.o depende de main.c y mod_error.h
	mod_error.o depende de mod_error.c y mod_error.h
	miprog depende de main.o y mod_error.o

	Lo que traducido en el Makrfile seria:

--/ Makefile /--

miprog: main.o mod_error.o
	gcc -o miprog main.o mod_error.o
main.o: main.c mod_error.h
	gcc -c main.c
mod_error.o: mod_error.c mod_error.h
	gcc -c mod_error.c

--/ Makefile /--

El uso del Makefile ofrece mas posiblidades que por ahora no veremos, ya 
que no lo veo necesario.

-= 5. Conclusion =-
   -------------

Hemos visto de forma muy superficial las facilidades con las que un 
sistema operativo nos brinda a la hora de programar. Asi mismo hemos hecho un
paseo por las posiblidades que tenemos, centrandonos, como no, en el lenguaje 
C, por ser este el mas usado actualmente a la hora de programar en los sistemas
UNIX.

Si bien en esta primera entrega de Linux Programing no hemos entrado 
realmente en lo que a la programacion se refiere, si que hemos visto ciertas
cosas que facilitaran al lector que no este familiarizado con la programacion 
a comprender mejor las entrgas que vendran en un futuro.

-=(EOF)=-





